#include <err.h>
#include <signal.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>

#include <nfc/nfc.h>
#include <nfc/nfc-types.h>

#include "nfc-utils.h"
#include "../src/fm1208.h"

#include "../utils/fm1208-utils.h"

static nfc_device *pnd = NULL;
static nfc_target nt ;

CMD_Response res;

uint8_t verbose = 0;

void
print_usage (const char* progname)
{
  printf ("usage: %s [-v 1/2/3]\n", progname);
  printf ("  -v\t verbose display\n");
}

void main (int argc ,char *argv[])
{
    const nfc_modulation nm = {
	    .nmt = NMT_ISO14443A,
	    .nbr = NBR_106,
    };
  
    const char *acLibnfcVersion = nfc_version ();

    printf ("%s uses libnfc %s\n", argv[0], acLibnfcVersion);
    if (argc != 1) {
        if ((argc == 3) && (0 == strcmp ("-v", argv[1]))) {
          switch(atoi(argv[2]))
          {
            case 3:
                setDebug(true);
            case 2:
            case 1:
                verbose = atoi(argv[2]);
                break;
            default:
                print_usage (argv[0]);
                exit (EXIT_FAILURE);
          }
        } else {
          print_usage (argv[0]);
          exit (EXIT_FAILURE);
        }
    }

    nfc_init (NULL);

    pnd = nfc_open (NULL, NULL);

    if (pnd == NULL) {
        printf ("%s", "Unable to open NFC device.\n");
        exit (EXIT_FAILURE);
    }

    if (nfc_initiator_init (pnd) < 0) {
        nfc_perror (pnd, "nfc_initiator_init");
        exit (EXIT_FAILURE);    
    }

printf ("NFC reader: %s opened\n", nfc_device_get_name (pnd));

    // Let the reader only try once to find a tag
    if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0) {
	    nfc_perror (pnd, "nfc_device_set_property_bool infinite select");
	    goto error;
    }
    
    if (nfc_initiator_select_passive_target (pnd, nm, NULL, 0, &nt) < 0) {
        nfc_perror (pnd, "nfc_initiator_select_passive_target");
        goto error;
    }
    
    if( verbose > 0 )
        print_nfc_target ( nt, true );

/////////////////////////////////////////////////////////

    uint8_t fid[2];

    for(int i=0x3f ;i<=0x3F;i+=1)
        for(int j=0 ;j<=0x32;++j)
        {
            fid[0] = i;
            fid[1] = j;
            SELECT(pnd, true, fid, sizeof(fid), &res);
            
            if (res.sw1sw2 != SW1SW2_NOSUCHFILE)
            {
                printf("\nDF:%02X%02X SW:%04X\ndata:",i,j,fid[0],fid[1],res.sw1sw2);
                print_hex(res.data,res.size);
                
                for(int i=1;i<32;++i)
                {
/*
                    {
                        uint8_t fid[2]={0};
                        fid[1]=i;
                        if ( SELECT(pnd, true, fid, sizeof(fid), &res) )
                        {
                            if (res.sw1sw2 == SW1SW2_SUCCESS)
                                printf("SELECT fid:%d SW:%04X\n",i,res.sw1sw2);
                        }
                        else
                            printf("READ_SELECT error!\n");
                    }
*/
                    if( READ_BINARY(pnd, i, 0,&res, 0) )
                        switch( res.sw1sw2 )
                        {
                            case SW1SW2_SUCCESS:
                                printf("fid:%d type:Binary data:",i);
                                print_hex(res.data,res.size);
                                break;
                            case SW1SW2_NOTCOMPATY:
                                if( READ_RECORD(pnd, false, i, 1, &res, 0) )
                                    switch( res.sw1sw2 )
                                    {
                                    case SW1SW2_SUCCESS:
                                        printf("fid:%d type:Record data:",i);
                                        print_hex(res.data,res.size);
                                        break;
                                    case SW1SW2_NOTCOMPATY:
                                        {
                                            uint8_t fid[2]={0};
                                            fid[1]=i;
                                            if ( SELECT(pnd, true, fid, sizeof(fid), &res) )
                                            {
                                                switch( res.sw1sw2 )
                                                {
                                                    case SW1SW2_SUCCESS:
                                                        printf("SELECT fid:%d SW:%04X NOTCOMPATY data:\n",i,res.sw1sw2);
                                                        print_hex(res.data,res.size);
                                                    break;
                                                    case SW1SW2_NOSUCHFILE:
                                                        printf("Unselectable! Maybe interal file? ");
                                                    default:
                                                        printf("SELECT fid:%d SW:%04X\n",i,res.sw1sw2);
                                                }
                                            }
                                            else
                                            {
                                                printf("SELECT error!\n");
                                                goto error;
                                            }
                                        }
                                        break;
                                    case SW1SW2_NORECORD:
                                        printf("fid:%d SW:%04X NORECORD\n",i,res.sw1sw2);
                                        break;
                                    default:
                                        printf("fid:%d SW:%04X UNKNOWN\n",i,res.sw1sw2);
                                    }
                                else
                                {
                                    printf("READ_RECORD error!\n");
                                    goto error;
                                }
                                break;
                            case SW1SW2_NOSUCHFILE:
                                break;
                            default:
                                printf("fid:%d SW:%04X UNKNOWN\n",i,res.sw1sw2);
                        }
                    else
                    {
                        printf("READ_BINARY error!\n");
                        goto error;
                    }
                }
            }
        }

	// Disconnect device and exit
	nfc_close(pnd);
    nfc_exit(NULL);
    exit (EXIT_SUCCESS);
error:
    nfc_close(pnd);
    nfc_exit(NULL);
    exit (EXIT_FAILURE);
}
